package ltd.hxya.novel.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ltd.hxya.novel.admin.entity.Operation;
import ltd.hxya.novel.admin.entity.Role;
import ltd.hxya.novel.admin.entity.UserRole;
import ltd.hxya.novel.admin.mapper.OperationMapper;
import ltd.hxya.novel.admin.mapper.RoleMapper;
import ltd.hxya.novel.admin.mapper.UserRoleMapper;
import ltd.hxya.novel.admin.service.IRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ltd.hxya.novel.admin.service.IUserService;
import ltd.hxya.novel.admin.vo.RoleVo;
import ltd.hxya.novel.admin.vo.UserVo;
import ltd.hxya.novel.common.bean.ResultEnum;
import ltd.hxya.novel.common.constant.ParamsConstant;
import ltd.hxya.novel.common.exception.NovelGlobalException;
import ltd.hxya.novel.common.utils.PageUtils;
import ltd.hxya.novel.common.vo.PageParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hty
 * @since 2022-10-04
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private OperationMapper operationMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private IUserService userService;

    @Override
    public Role roleByUserId(Integer userId) {
        Role role = roleMapper.roleByUserId(userId);
        return role;
    }

    @Override
    public Page<Role> roleList(Role role) {
        //获取page信息
        PageParam pageParmas = PageUtils.getPageParams();
        //构造sql
        QueryWrapper<Role> roleQueryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(role.getRoleKey())){
            roleQueryWrapper.eq("role_key",role.getRoleKey());
        }
        if (!StringUtils.isEmpty(role.getRoleName())){
            roleQueryWrapper.eq("role_name",role.getRoleName());
        }
        if (!StringUtils.isEmpty(role.getRoleStatus())){
            roleQueryWrapper.eq("role_status",role.getRoleStatus());
        }
        Map<String, Object> params = role.getParams();

        if (!CollectionUtils.isEmpty(params)){
            String beginTime = (String) role.getParams().get(ParamsConstant.BEGIN_TIME);
            String endTime = (String) role.getParams().get(ParamsConstant.END_TIME);
            if (!StringUtils.isEmpty(endTime)){
                roleQueryWrapper.le("create_time",endTime);
            }
            if (!StringUtils.isEmpty(beginTime)){
                roleQueryWrapper.ge("create_time",beginTime);
            }

        }


        Page<Role> rolePage = this.page(new Page<Role>(pageParmas.getCurrent(), pageParmas.getSize()), roleQueryWrapper);
        return rolePage;
    }

    @Override
    public RoleVo roleInfo(Integer roleId) throws ExecutionException, InterruptedException {

        CompletableFuture<Role> roleCompletableFuture = CompletableFuture.supplyAsync(() -> this.baseMapper.selectById(roleId));
        //通过roleId查询操作相关的信息
        CompletableFuture<List<Operation>> operationCompletableFuture = CompletableFuture.supplyAsync(() -> operationMapper.operationsByRoleId(roleId));

        CompletableFuture.allOf(roleCompletableFuture,operationCompletableFuture).get();
        RoleVo roleVo = new RoleVo();
        BeanUtils.copyProperties(roleCompletableFuture.get(),roleVo);
        roleVo.setOperations(operationCompletableFuture.get());
        return roleVo;
    }

    @Override
    public Page<UserVo> grantedUser(UserVo userVo) {

        Page<UserVo> userVoPage = userService.grantedUser(userVo);
        //根据roleId的信息查询userVo
        return userVoPage;
    }

    @Override
    public Page<UserVo> ungrantedUser(UserVo userVo) {

        Page<UserVo> userVoPage = userService.ungrantedUser(userVo);
        return userVoPage;
    }

    @Override
    public int grantRole(Integer roleId, Integer[] userIds) {
        //批量插入相关数据
        //将roleId和userIds封装成对象
        List<UserRole> userRoles =new ArrayList<>();
        for (Integer userId : userIds) {
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(userId);
            userRoles.add(userRole);
        }

        int row = userRoleMapper.insertUserRole(userRoles);

        return row;
    }

    @Override
    public int revokeAll(Long roleId, Long[] userIds) {

        //通过UserMapper删除相关授权
        return userRoleMapper.revokeAll(roleId,userIds);
    }

    /**
     * 根据id删除角色
     * @param ids
     */
    @Override
    public void deleteById(Integer[] ids) {
        List<Integer> idList = Arrays.asList(ids);
        this.baseMapper.deleteBatchIds(idList);
    }

    /**
     *添加角色的处理
     * @param role
     */
    @Override
    public void addRole(Role role) {
        // 判断role_name是否是唯一的，是唯一的在进行添加处理
        if (StringUtils.isEmpty(role)){
            throw new NovelGlobalException(ResultEnum.NOT_DATA.getCode(),ResultEnum.NOT_DATA.getMsg());
        }
        String roleName = role.getRoleName();
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_name",roleName);
        Long aLong = baseMapper.selectCount(queryWrapper);
        if (aLong>=1){
            // 角色已经存在，不能进行添加处理
            throw new NovelGlobalException(ResultEnum.USER_NAME_IS_REGISTER.getCode(),ResultEnum.USER_NAME_IS_REGISTER.getMsg());
        }
        role.setCreateTime(LocalDateTime.now());
        this.baseMapper.insert(role);
    }

    /**
     * 角色修改的处理
     * @param role
     */
    @Override
    public void updateRole(Role role, HttpServletRequest  request) {
        // 1、判断角色是否允许操纵处理和判空操作
        String roleKey = role.getRoleKey();
        if (!StringUtils.isEmpty(role) &&  roleKey.equals("admin")){
            throw new NovelGlobalException(410,"不允许操作超级管理员角色");
        }
        // 2、判断当前用户是否有操作的权限
        // 2.1、根据获取到token，然后用JWT获取到userId
//        String userCookieToken = getUserCookieToken(request);
//        if (userCookieToken == null){
//            throw new NovelGlobalException(410,"获取token失败");
//        }

        // 3、效验角色名称的唯一性以及key的唯一性
        if (checkRoleNameUnique(role) && checkRoleKeyUnique(role)){
            role.setUpdateTime(LocalDateTime.now());
            baseMapper.updateById(role);
        }else throw new NovelGlobalException(410,"错误处理");
    }



    /**
     * 获取所有的Role
     */
    @Override
    public List<Role> getRoleAll() {
        List<Role> roles = baseMapper.selectList(null);
        return roles;
    }

    /**
     * TODO 这个前端没显示出来，前端还是采用显示全部角色
     * 根据roleIdlist可以查询到对应的role了
     * @param roleList
     * @return   根据roleList返回对应的RoleList
     */
    @Override
    public List<Role> getRolesList(List<Integer> roleList) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("role_id", roleList);
        List<Role> roles = baseMapper.selectList(queryWrapper);
        return roles;
    }

    /**
     * 判断角色名称是否一致
     * @param role 页面修改传过来的信息
     * @return
     */
    public Boolean checkRoleNameUnique(Role role){
        if (ObjectUtils.isEmpty(role)){
            throw new NovelGlobalException(ResultEnum.NOT_DATA.getCode(),ResultEnum.NOT_DATA.getMsg());
        }
        String roleName = role.getRoleName();
        Integer roleId = role.getRoleId();
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_name",roleName);
        queryWrapper.last("limit 1");
        Role role1 = baseMapper.selectOne(queryWrapper);
        // 他不是空，并且还有第二个数据，就表示不是唯一的
        if (!StringUtils.isEmpty(role1) && role1.getRoleId() != roleId){
            return false;
        }
        return true;
    }


    /**
     * 判断key是否一致
     * @param role
     * @return
     */
    public Boolean checkRoleKeyUnique(Role role){
        if (ObjectUtils.isEmpty(role)){
            throw new NovelGlobalException(ResultEnum.NOT_DATA.getCode(),ResultEnum.NOT_DATA.getMsg());
        }
        String roleKey = role.getRoleKey();
        Integer roleId = role.getRoleId();
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_key",roleKey);
        queryWrapper.last("limit 1");
        Role role1 = baseMapper.selectOne(queryWrapper);
        if (!StringUtils.isEmpty(role1) && role1.getRoleId() != roleId){
            return false;
        }
        return true;
    }


    private String getUserCookieToken(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null || cookies.length == 0) {
            return null;
        }
        for (Cookie cookie : cookies) {
            String name = cookie.getName();
            if (name.equals("admin-authorization")) {
                return cookie.getValue();
            }
        }
        return null;
    }
}
